/*
 * Fichier: GenerateJnlp.java
 * Crée le: 28 juin 2007.
 * Modifié: 20 juin 2012.
 * Auteurs: Sébastien ESTIENNE.
 * SiteWeb: http://www.prog-info.org/
 * 
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 */

package generator.jnlp;



import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;

import javaexos.model.ChapterModel;
import javaexos.model.ExerciseModel;

import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerConfigurationException;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.TransformerFactoryConfigurationError;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;

import org.w3c.dom.Comment;
import org.w3c.dom.Document;
import org.w3c.dom.Element;



/**
 * <p>Génère un fichier Jnlp pour les exercices de Developpez.</p>
 * @author Sébastien ESTIENNE.
 */
public class GenerateJnlp
{
   /** Adresse du site web perso de developpez.com. */
   private static final String WEB_ADDRESS = "http://sebastien-estienne.developpez.com/";
   
   /**
    * <p>Ecrit un fichier Jnlp pour les exercices de Developpez.</p>
    * @param directory Le chemin vers le fichier.
    * @param chapter Le chapitre concerné.
    * @param exercise L'exercice du chapitre concerné. 
    * @return true si le fichier a été écrit avec succès sinon false.
    */
   public static boolean ecrireJnlp(String directory, ChapterModel chapter, ExerciseModel exercise)
   {
      // Le résultat de l'écriture du fichier.
      boolean result = true;

      // Le chemin du fichier.
      File file = new File(directory + exercise.getName() + ".jnlp");

      // Supprime le fichier s'il existe déjà.
      if(file.exists())
      {
         file.delete();
      }
      
      // Défini le chemin vers le tutoriel.
      String tutorial;
      if(chapter.isValidated())
      {
         tutorial = "tutoriels/java/";
      }
      else
      {
         tutorial = "encours/";
      }

      // Ecrit le fichier jnlp.
      StreamResult streamResult = null;
      FileInputStream inStream = null;
      FileOutputStream outStream = null;
      try
      {
         // Création du document représenté sous forme de DOM.
         Document doc = DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument();
         
         // Ajout d'un commentaire.
         Comment comment = doc.createComment("File " + exercise.getName() + ".jnlp");
         doc.appendChild(comment);
         
         // Création de la balise racine jnlp.
         Element jnlp = doc.createElement("jnlp");
         jnlp.setAttribute("spec", "1.5+");
         String codebase = WEB_ADDRESS + tutorial + chapter.getName() + "/fichiers/";
         jnlp.setAttribute("codabase", codebase);
         String href = WEB_ADDRESS + tutorial + chapter.getName() + "/";
         jnlp.setAttribute("href", href + exercise.getName() + ".jnlp");
         doc.appendChild(jnlp);
         
         // Information.
         Element info = doc.createElement("information");
         jnlp.appendChild(info);
         
         Element title = doc.createElement("title");
         title.setTextContent(exercise.getTitle());
         info.appendChild(title);
         
         Element vendor = doc.createElement("vendor");
         vendor.setTextContent("Sébastien ESTIENNE");
         info.appendChild(vendor);
         
         Element homepage = doc.createElement("homepage");
         homepage.setAttribute("href", WEB_ADDRESS);
         info.appendChild(homepage);
         
         Element description = doc.createElement("description");
         description.setTextContent("Exercice " + exercise.getNumber() + " : " + exercise.getTitle());
         info.appendChild(description);
         
         Element shortDesc = doc.createElement("description");
         shortDesc.setAttribute("kind", "short");
         description.setTextContent("Chapitre " + chapter.getNumber() + " : " + chapter.getTitle() 
               + ", Exercice " + exercise.getNumber() + " : " + exercise.getTitle() + ".");
         info.appendChild(shortDesc);
         
         Element icon = doc.createElement("icon");
         icon.setAttribute("href", "icone_dvlp.png");
         info.appendChild(icon);
         
         Element offline = doc.createElement("offline-allowed");
         info.appendChild(offline);
         
         // Security.
         Element secu = doc.createElement("security");
         jnlp.appendChild(secu);
         
         Element permissions = doc.createElement("all-permissions");
         secu.appendChild(permissions);
         
         // Resources.
         Element resources = doc.createElement("resources");
         jnlp.appendChild(resources);
         
         Element j2se = doc.createElement("j2se");
         j2se.setAttribute("version", "1.5+");
         resources.appendChild(j2se);
         
         Element jar = doc.createElement("jar");
         jar.setAttribute("href", exercise.getName() + ".jar");
         resources.appendChild(jar);
         
         // Application description.
         Element app = doc.createElement("application-desc");
         String mainClass = "chapitre" + chapter.getNumber() + "." + exercise.getMainClass();
         app.setAttribute("main-class", mainClass);
         jnlp.appendChild(app);
         
         // Ecriture du document XML dans un fichier.
         Transformer transformer = TransformerFactory.newInstance().newTransformer();
         transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "3");
         transformer.setOutputProperty(OutputKeys.INDENT, "yes");
         streamResult = new StreamResult(new OutputStreamWriter(new FileOutputStream(file), 
               "UTF-8"));
         transformer.transform(new DOMSource(doc), streamResult);
         
         // Passe le fichier en format UNIX.
         StringBuilder xmlContent = new StringBuilder();
         inStream = new FileInputStream(file);
         BufferedReader inBuffer = new BufferedReader(new InputStreamReader(inStream, "UTF-8"));
         int c;
         while ((c = inBuffer.read()) != -1)
         {
            if(c != 13)
            {
               xmlContent.append((char) c);
            }
         }
         inBuffer.close();
         outStream = new FileOutputStream(file);
         BufferedWriter outBuffer = new BufferedWriter(new OutputStreamWriter(outStream, "UTF-8"));
         outBuffer.append(xmlContent.toString());
         outBuffer.close();
      }
      catch(IOException e)
      {
         e.printStackTrace();
         result = false;
      }
      catch (ParserConfigurationException e)
      {
         e.printStackTrace();
         result = false;
      }
      catch (TransformerConfigurationException e)
      {
         e.printStackTrace();
         result = false;
      }
      catch (TransformerFactoryConfigurationError e)
      {
         e.printStackTrace();
         result = false;
      }
      catch (TransformerException e)
      {
         e.printStackTrace();
         result = false;
      }
      finally
      {
         try
         {
            if(streamResult != null && streamResult.getOutputStream() != null)
            {
               streamResult.getOutputStream().close();
            }
            if(inStream != null)
            {
               inStream.close();
            }
            if(outStream != null)
            {
               outStream.close();
            }
         }
         catch (IOException e)
         {
            e.printStackTrace();
         }
      }

      return result;
   }
}
